-- Main
-- 游戏主入口

-- 需要进行单元测试
_G["TEST"] = false;

require "Config"

-- 开启垃圾回收功能
function enableGC()
    collectgarbage("collect");
    collectgarbage("setpause", 100);
    collectgarbage("setstepmul", 5000);
end

-- 禁止垃圾回收功能
function disableGC()
    collectgarbage("stop");
end

-- 清除重大公告提前加载的部分
function clearMyRequire()
    for _, file in pairs(_G["myRequire"]) do
        package.loaded[file] = false;
    end
    _G["myRequire"] = nil;
    _G["gameScene"] = nil;

    -- 把字体搜索路径去掉
    local search_paths = cc.FileUtils:getInstance():getSearchPaths();
    for index, search_path in pairs(search_paths) do
        if search_path == cc.FileUtils:getInstance():getWritablePath() .. "update_res/res/" then
            table.remove(search_paths, index);
            break;
        end
    end
    cc.FileUtils:getInstance():setSearchPaths(search_paths);
end

-- 重新加载文件
function reloadLuaFile(target)
    package.loaded[target] = false;
    require(target);
end

-- 显示重大公告界面
function showImportantBoard()
    _G["myRequire"] = {};
    local function myRequire(file)
        require(file);
        table.insert(_G["myRequire"], file);
    end

    _G["gameScene"] = true;

    -- 加载需要的文件
    local needFires = {
        "game/ui/form/login/UIOutBoard",
        "game/ui/form/setting/UIGameBoard",
        "game/logic/module/GameBoardM",
        "game/ui/base/util/ScrollTool",
        "game/ui/base/util/Text",
        "game/ui/base/TextStyleM",
        "game/ui/base/util/Node",
        "game/ui/base/util/ScrollTool",
        "game/ui/UIConsts",
        "game/loc/localization",
        "game/ui/misc/UIIndicator",
        "core/base/Table",
        "game/ui/base/AlignM",
        "game/scene/FormEffectM",
        "game/logic/module/TimeM",

    };
    for _, file in pairs(needFires) do
        myRequire(file);
    end

    local scene = require("game/scene/BoardScene");
    table.insert(_G["myRequire"], "game/scene/BoardScene");
    table.insert(_G["myRequire"], "game/scene/SceneBase");
    -- 需要把自身也包含进来
    table.insert(_G["myRequire"], "Main");

    _G["gameScene"] = scene;
    local gameScene = scene.create();
    _G["gameScene"] = gameScene;

    -- 转到公告场景
    if cc.Director:getInstance():getRunningScene() then
        cc.Director:getInstance():replaceScene(gameScene);
    else
        cc.Director:getInstance():runWithScene(gameScene);
    end
end

-- 检查重大公告
function checkImportantBoard()
    require "game/logic/module/UserProtocolM"

    if UserProtocolM.needReadUserProtocol() then
        -- 需要阅读用户协议
        return true;
    end

    if _G["outBoard"] and not _G["hasShowBoard"] then
        -- 有重大公告要显示
        return true;
    end

    return false;
end

-- 预加载主场景的代码
function preloadMain()
    if LUA_COVERAGE == 1 then
        _G["luaRunner"] = require "luacov.luacov";
    end

    require "cocos/init"
    require "core/StartCore"
    require "game/StartGame"
    require "core/base/UserDefaultM"
    require "game/base/commonUtil"
    require "game/base/options"
    require "game/loc/localization"
    require "game/ui/base/util"
    require "game/ui/UIMgr"

    if DEBUG_MODE == 1 then
        -- 单元测试代码
        require("UnitTest");

        -- 压力测试
        require("StressTest");
    end

    -- 重新加载core相关代码，要求重新加载的文件中没有全局变量
    reloadLuaFile("core.base.Debug");

    -- 非DEBUG模式下，不做性能统计
    if DEBUG_MODE ~= 1 then
        Profiler.funcBegin = function() end;
        Profiler.funcEnd = function() end;
    end

    disableGC();

    printLuaMemSize("main");

    Profiler.funcBegin("main");

    -- 检查语言包所需资源是否存在，如果不存在，则默认设置为英文
    -- 不存在的原因可能为玩家在网络不通的时候开启游戏，则进入游戏时语言包还未下载
    if not cc.FileUtils:getInstance():isFileExist(getLocFontName()) then
        if getLang() == "tw" then
            -- 标记清零，表示需要重新下载
            cc.UserDefault:getInstance():setStringForKey("lang_tw", "0");
        end

        setLang("en");
        initLang();
    end

    -- 先启动内核
    startCore();

    printLuaMemSize("after startCore");

    -- 启动游戏
    startGame();

    EventMgr.fire(event.PRELOAD_MAIN_OK);

    printLuaMemSize("after startGame");

    -- 启动单元测试
    -- UnitTest.test();

    -- 压力测试
    --StressTest.start();

    enableGC();
    Profiler.funcEnd("main");
    printLuaMemSize("after enableGC");
end

local function main()
    if checkImportantBoard() then
        -- 有重大公告要显示
        -- 外部调用showImportantBoard
        return;
    end

    preloadMain();
end

main();

-- 程序切换到后台
function applicationDidEnterBackground()
    print("enter background");

    local scene = cc.Director:getInstance():getRunningScene();
    if scene and scene:getName() == "BoardScene" then
        -- 重大公告场景，以下均不处理
        return;
    end

    showPauseForm();

    if not HeartBeatM then
        return;
    end

    -- 关闭心跳
    HeartBeatM.stop();

    ScheduleM.pause();

    -- 自动战斗暂停
    AutoFightM.pause();

    -- 注册推送事件
    if isAndroidPlatform() or isIphonePlatform() or isIpadPlatform() then
        setLocalPush();
    end
end

-- 切换到前台的时间
appEnterForegroundTime = 0;

-- 程序切换到前台
function applicationWillEnterForeground()
    print("enter foreground");
    appEnterForegroundTime = os.time();

    local scene = cc.Director:getInstance():getRunningScene();
    if scene and scene:getName() == "BoardScene" then
        -- 重大公告场景，以下均不处理
        return;
    end

    hidePauseForm();

    if not HeartBeatM then
        return;
    end

    ScheduleM.resume();

    AudioM.setDefaultVolume();

    -- 开启心跳
    HeartBeatM.start();

    -- 自动战斗继续（安卓下切到后台后自动战斗停止，需要手工继续，否则可能报错）
    if isWindowsPlatform() then
        AutoFightM.continue();
    end

    -- 反注册推送事件
    if isAndroidPlatform() or isIphonePlatform() or isIpadPlatform() then
        clearLocalPush();
    end

    if MarketM.isRecharging() then
        -- 取消正在充值的标记
        MarketM.setRechargingFlag(false);
    end

    -- 同步服务器时间
    TimeM.sync();
end

-- 程序大小改变
function applicationScreenSizeChanged(width, height)
    print("[lua]applicationScreenSizeChanged, width:"..width..",height:"..height);

    local oldSize = cc.Director:getInstance():getOpenGLView():getFrameSize();
    if oldSize.width ~= width or oldSize.height ~= height then
        print("applicationScreenSizeChanged, width:"..width..",height:"..height);

        local size = cc.Director:getInstance():getOpenGLView():getDesignResolutionSize();

        cc.Director:getInstance():getOpenGLView():setFrameSize(width, height);
        cc.Director:getInstance():getOpenGLView():setDesignResolutionSize(size.width, size.height, 0);
        cc.Director:getInstance():setViewport();
    end
end

-- 处理返回键事件（安卓下的处理）
function onBackEvent()
    print("back event");
    UIMgr.handleBackEvent();
end

-- 找不到文件回调处理
function onFileMissing(filename)
    printR("onFileMissing:"..filename)
    local function callback()

    end

    -- 上报到配置的后台
    if MISSING_FILE_URL then
        postDataToRemoteHost(MISSING_FILE_URL, filename, callback)
    end
end

-- 打开GD界面
function openGdUI()
    local curFormName = UIMgr.getCurrentScene():getCurrentForm():getName();
    if curFormName == "UIDungeonMain" or curFormName == "UINewWorkshop" then
        return;
    end

    require "game/ui/form/setting/UIGD"
    local uiGd = UIGD.create();
    UIMgr.getCurrentScene():addForm(uiGd);
end